/*
 * ImportSources module for Netbeans.
 *
 * Copyright (c) 2007, Rogue
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * For queries or bugs, you may contact me via e-mail: roguexz [at] gmail [dot] com
 */
package rogue.netbeans.module.importsources;

import java.io.File;
import java.io.FileFilter;
import rogue.netbeans.module.importsources.ui.JCheckBoxTreeNode;

/**
 * Scans a specified directory for files matching the filter criteria. This class
 * also updates any notifiers listening for the current file being scanned.
 *
 * @author Rogue
 */
public class ScanFiles {
    private String rootDirectory = null;
    private String[] fileExtensions = null;
    private boolean scanComplete = false;
    private FileFilter ff = null;
    private volatile boolean terminateScan = false;
    private StatusNotifier notifier = null;
    
    /** Creates a new instance of ScanFiles */
    public ScanFiles(String rootDirectory, String[] fileExtensions, StatusNotifier notifier) {
        this.rootDirectory = rootDirectory;
        this.fileExtensions = fileExtensions;
        this.notifier = notifier;
    }
    
    public void terminateScan() {
        this.terminateScan = true;
    }
    
    public JCheckBoxTreeNode getSelectedFiles() {
        scanComplete = false;
        terminateScan = false;
        if(rootDirectory==null) {
            return null;
        }
        
        scanComplete = false;
        File root = new File(rootDirectory);
        
        this.ff = new FileFilter() {
            public boolean accept(File pathname) {
                if(pathname.isDirectory()) {
                    return true;
                }
                for(int i=0; i<fileExtensions.length; i++) {
                    if(pathname.toString().endsWith(fileExtensions[i])) {
                        return true;
                    }
                }
                return false;
            }
        };
        if(!terminateScan) {
            JCheckBoxTreeNode node = getMatchingFiles(root);
            scanComplete = true;
            notifier.updateStatus("");
            return node;
        }
        
        scanComplete = false;
        return null;
    }
    
    public boolean isScanComplete() {
        return scanComplete;
    }
    
    private JCheckBoxTreeNode getMatchingFiles(File parentDir) {
        JCheckBoxTreeNode parentNode = new JCheckBoxTreeNode(parentDir.getName(), true,true);
        
        for(File f: parentDir.listFiles(ff)) {
            // Add the plug for displaying the directory being scanned at the moment.
            if(terminateScan) {
                parentNode = null;
                notifier.updateStatus("Scan terminated.");
                break;
            }
            
            notifier.updateStatus(
                    new StringBuilder("Scanning: ").append(f.toString()).toString()
                    );
            
            JCheckBoxTreeNode node = null;
            if(f.isDirectory()) {
                node = getMatchingFiles(f);
                if(node==null || node.getChildCount()==0) {
                    // ignore and continue.
                    continue;
                }
            } else {
                node = new JCheckBoxTreeNode(f.getName(), true, true);
            }
            
            // add it to the current node.
            parentNode.add(node);
        }
        
        return parentNode;
    }
    
}
